# -*- coding: utf-8 -*-

"""
DateTime   : 2020/12/24 21:11
Author     : ZhangYafei
Description: 
"""
from prettytable import PrettyTable
import numpy as np

""" 1. 打印系统菜单 """
print('=' * 30)
print('|', end='')
print('学生信息管理系统'.center(20), end='')
print('|')
print('|', end='')
print('版本 V1.0'.center(26), end='')
print('|')
print('-' * 30)
print('|', end='    ')
print('   用户操作说明'.ljust(18), end='')
print('|')
print('-' * 30)
print('|', end='   ')
print("1. 添加学生信息".ljust(19), end='')
print('|')
print('|', end='   ')
print("2. 删除学生信息".ljust(19), end='')
print('|')
print('|', end='   ')
print("3. 修改学生信息".ljust(19), end='')
print('|')
print('|', end='   ')
print("4. 查询学生信息".ljust(19), end='')
print('|')
print('|', end='   ')
print("5. 打印所有学生信息".ljust(15), end='')
print('|')
print('|', end='   ')
print("6. 课程信息统计".ljust(19), end='')
print('|')
print('|', end='   ')
print("7. 打印系统菜单".ljust(19), end='')
print('|')
print('|', end='   ')
print("8. 退出系统".ljust(21), end='')
print('|')
print('=' * 30)

students = []
students.append({'学号': '121212', '姓名': '学生A', 'C语言': 80, 'Python': 85, '数据库': 90, '平均分': 85.0})
students.append({'学号': '2121', '姓名': '学生B', 'C语言': 83, 'Python': 75, '数据库': 70, '平均分': 76.0})
students.append({'学号': '12121', '姓名': '学生C', 'C语言': 87, 'Python': 95, '数据库': 80, '平均分': 87.33})
students.append({'学号': '121212', '姓名': '学生D', 'C语言': 75, 'Python': 80, '数据库': 83, '平均分': 79.33})

while True:
    choice = input('请选择您需要执行的操作（Q/q退出,M/m打印菜单）>> ')
    if choice == '1':
        while True:
            stu_id = input('请输入学号 (B/b返回主菜单) >> ').strip()
            if not stu_id:
                print('学号不能为空，请重新输入！')
                continue
            elif stu_id.lower() == 'b':
                break
            for student in students:
                if stu_id == student['学号']:
                    print('\033[1;32m', end='')
                    print(f'对不起，{stu_id} 已经添加过了', end='')
                    print('\033[0m')
                    break
            else:
                while True:
                    name = input('请输入姓名 (B/b返回主菜单) >> ').strip()
                    if name.lower() == 'b':
                        break
                    if not name:
                        print('\033[1;32m', end='')
                        print('姓名不能为空，请重新输入！', end='')
                        print('\033[0m')
                        continue
                    score_c = input('请输入C语言课程成绩 >> ')
                    score_python = input('请输入Python课程成绩 >> ')
                    score_sql = input('请输入数据库课程成绩 >> ')
                    if score_c.isdecimal() and score_python.isdecimal() and score_sql.isdecimal():
                        score_c = float(score_c)
                        score_python = float(score_python)
                        score_sql = float(score_python)
                    else:
                        print('输入的成绩必须为数字且不能为空，请重新录入')
                        continue
                    total_score = sum([score_c, score_python, score_sql]) / 3
                    students.append({'学号': stu_id, '姓名': name, 'C语言': score_c, 'Python': score_python, '数据库': score_sql,
                                     '平均分': total_score})
                    print('\033[1;32m', end='')
                    print(f'学号为：{stu_id} 的学生信息添加成功!')
                    break
                break
    elif choice == '2':
        stu_id = input('请输入您要删除学生信息的学号 >> ')
        for index, student in enumerate(students):
            if stu_id == student['学号']:
                name = student['姓名']
                print(f'确认要删除学号为 {stu_id}，姓名为 {name} 的信息吗？')
                delete_choice = input('是否确认删除？(输入Y/y确认，其他取消) >> ')
                print('\033[1;32m', end='')
                if delete_choice.lower() == 'y':
                    del students[index]
                    print(f'学号为 {stu_id} 的学生信息删除成功！')
                else:
                    print('已取消删除操作')
                print('\033[0m', end='')
                break
        else:
            print('\033[1;32m', end='')
            print(f'对不起，学号为 {stu_id} 的学生信息不存在!')
            print('\033[0m', end='')
            continue
    elif choice == '3':
        stu_id = input('请输入您要修改学生信息的学号(B/b返回上一级) >> ')
        print('\033[1;32m', end='')
        for student in students:
            if stu_id == student['学号']:
                print('查询到的学生信息为：')
                print('\033[1;31m', end='')
                table = PrettyTable(['学号', '姓名', 'C语言', 'Python', '数据库'])
                table.add_row([stu_id, student['姓名'], student['C语言'], student['Python'], student['数据库']])
                print(table, end='')
                print('\033[0m')
                while True:
                    mod_field = input('请输入要修改的字段(B/b返回上一级) >> ')
                    if mod_field.lower() == 'b':
                        break
                    if mod_field not in student or mod_field == '平均分':
                        print('您输入的字段不存在，请重新输入！')
                        continue
                    new_value = input('请输入该字段的新值 >> ')
                    if mod_field == '学号':
                        for stu in students:
                            if stu['学号'] == new_value:
                                print('该学号已经添加过，请勿重复添加')
                                break
                        else:
                            student[mod_field] = new_value
                            stu_id = new_value
                    elif mod_field != '姓名':
                        if new_value.isdecimal():
                            new_value = float(new_value)
                            student[mod_field] = new_value
                            _, score_c, score_python, score_sql, _ = student.values()
                            total_score = sum([score_c, score_python, score_sql])
                            mean_score = round(total_score / (len(student) - 1), 2)
                            student['平均分'] = mean_score
                        else:
                            print('分数必须是数字')
                            continue
                    else:
                        student[mod_field] = new_value
                    print('\033[1;32m', end='')
                    print(f'学号为 {stu_id} 的 {mod_field} 已经修改为 {new_value}', end='')
                    print('\033[0m')
                break
        else:
            print(f'对不起，学号为 {stu_id}的学生信息不存在!')
            continue
    elif choice == '4':
        # 学生信息查询
        while True:
            stu_id = input('请输入您要查询学生信息的学号(B/b返回主菜单) >> ').strip()
            print("\033[1;32m", end='')
            if stu_id.lower() == 'b':
                break
            if not stu_id:
                print('学号不能为空，请重新输入!')
                print('\033[0m', end='')
                continue
            mean_score_list = [stu['平均分'] for stu in students]
            mean_score_list.sort(reverse=True)
            table = PrettyTable(['学号', '姓名', 'C语言', 'Python', '数据库', '平均分', '排名'])
            for student in students:
                if student['学号'] == stu_id:
                    print('查询到的学生信息为：')
                    print("\033[1;31m", end='')
                    stu_id, name, score_c, score_python, score_sql, mean_score = student.values()
                    mean_score_order = mean_score_list.index(mean_score) + 1
                    table.add_row([stu_id, name, score_c, score_python, score_sql, mean_score, mean_score_order])
                    print(table)
                    print('\033[0m', end='')
                    break
            else:
                print(f'对不起，学号为 {stu_id} 的学生信息不存在!')
                print('\033[0m', end='')
                continue
    elif choice == '5':
        # 查询所有学生信息及实现排序功能
        print('\033[1;32m', end='')
        if len(students) == 0:
            print(f'当前暂无学生信息', end='')
            print('\033[0m')
            continue
        students_nums = len(students)
        print(f'共查询到 {students_nums} 条记录，查询结果如下：')
        print('\033[1;31m', end='')
        table = PrettyTable(['学号', '姓名', 'C语言', 'Python', '数据库', '平均分', '排名'])
        students_sorted_total = sorted(students, key=lambda x: x['平均分'], reverse=True)
        total_score_order_dict = {student['学号']: index + 1 for index, student in enumerate(students_sorted_total)}
        for student in students:
            stu_id, name, score_c, score_python, score_sql, mean_score = student.values()
            table.add_row([stu_id, name, score_c, score_python, score_sql, mean_score, total_score_order_dict[stu_id]])
        print(table)
        print('\033[0m', end='')
        sort_confirm = input('是否选择排序？（Y/n确认，其他返回上一级）>> ')
        if sort_confirm.lower() != 'y':
            print('\033[0m', end='')
            continue
        table = PrettyTable(['排序方式'])
        table.add_row(['1. C语言成绩 2. Python成绩 3. 数据库成绩 4. 总成绩'])
        table.add_row(['desc-降序, asc-升序'])
        table.add_row(['(以空格分开，默认为desc; 如1 asc，表示按C语言成绩升序)'])
        print('\033[1;32m', end='')
        print(table, end='')
        print('\033[0m')
        while True:
            # print('\033[1;32m', end='')
            sort_param = input('请输入排序方式(M/m打印排序菜单，回车返回主菜单) >> ').strip()
            print('\033[1;32m', end='')
            if not sort_param:
                break
            if sort_param.lower() == 'm':
                table = PrettyTable(['排序方式'])
                table.add_row(['1. C语言成绩 2. Python成绩 3. 数据库成绩 4. 总成绩'])
                table.add_row(['desc-降序, asc-升序'])
                table.add_row(['(以空格分开，默认为desc; 如1 asc，表示按C语言成绩升序)'])
                print(table)
                print('\033[0m', end='')
                continue
            if len(sort_param.split(' ')) < 1 or len(sort_param.split(' ')) > 2:
                print('请输入的排序方式有误，请重新输入')
                print('\033[0m', end='')
                continue
            sort_dict = {'1': 'C语言', '2': 'Python', '3': '数据库', '4': '平均分'}
            params = sort_param.split()
            if params[0] not in sort_dict:
                print('请输入的排序方式有误，请重新输入')
                print('\033[0m', end='')
                continue
            sort1 = sort_dict[params[0]]
            sort2 = False if len(params) == 2 and params[1] == 'asc' else True
            students_sorted_class = sorted(students, key=lambda x: x[sort1], reverse=sort2)
            print(f'按 {sort1} {"desc" if sort2 else "asc"} 排序结果如下：')
            print('\033[1;31m', end='')
            table = PrettyTable(['学号', '姓名', 'C语言', 'Python', '数据库', '平均分', f'排名-{sort1}', '总排名'])
            for index, student in enumerate(students_sorted_class, start=1):
                index = index if sort2 else students_nums - index + 1
                stu_id, name, score_c, score_python, score_sql, mean_score = student.values()
                table.add_row(
                    [stu_id, name, score_c, score_python, score_sql, mean_score, index, total_score_order_dict[stu_id]])
            print(table)
            print('\033[0m', end='')
    elif choice == '6':
        # 课程信息统计
        print('\033[1;32m', end='')
        class_table = PrettyTable(['课程'])
        class_table.add_row(['1. C语言 2. Python 3. 数据库 0. 所有课程'])
        print(class_table, end='')
        print('\033[0m')
        while True:
            class_id = input('请选择你要查看的课程(M/m打印课程菜单，回车返回主菜单) >> ').strip()
            if not class_id:
                break
            if class_id.lower() == 'm':
                print('\033[1;32m', end='')
                print(class_table, end='')
                print('\033[0m')
                continue
            class_c = []
            class_python = []
            class_sql = []
            if class_id == '1':
                for student in students:
                    class_c.append(student['C语言'])
            elif class_id == '2':
                for student in students:
                    class_python.append(student['Python'])
            elif class_id == '3':
                for student in students:
                    class_sql.append(student['数据库'])
            elif class_id == '0':
                for student in students:
                    class_c.append(student['C语言'])
                    class_python.append(student['Python'])
                    class_sql.append(student['数据库'])
            else:
                print('您选择的课程有误，请重新选择！')
                continue
            table = PrettyTable(['课程', '最高分', '最低分', '平均分', '中位数', '及格人数', '不及格人数', '总人数'])
            if class_c:
                class_c_nums, class_c_max, class_c_min, class_c_mean, class_c_median = len(class_c), max(class_c), min(
                    class_c), np.mean(class_c), np.median(class_c)
                class_c_pass = class_c_fail = 0
                for score in class_c:
                    if score >= 60:
                        class_c_pass += 1
                    else:
                        class_c_fail += 1
                table.add_row(
                    ['C语言', class_c_max, class_c_min, class_c_mean, class_c_median, class_c_pass, class_c_fail,
                     class_c_nums])
            if class_python:
                class_python_nums, class_python_max, class_python_min, class_python_mean, class_python_median = len(
                    class_python), max(class_python), min(class_python), np.mean(class_python), np.median(class_python)
                class_python_pass = class_python_fail = 0
                for score in class_python:
                    if score >= 60:
                        class_python_pass += 1
                    else:
                        class_python_fail += 1
                table.add_row(['Python', class_python_max, class_python_min, class_python_mean, class_python_median,
                               class_python_pass, class_python_fail, class_python_nums])
            if class_sql:
                class_sql_nums, class_sql_max, class_sql_min, class_sql_mean, class_sql_median = len(class_sql), max(
                    class_sql), min(class_sql), np.mean(class_sql), np.median(class_sql)
                class_sql_pass = class_sql_fail = 0
                for score in class_sql:
                    if score >= 60:
                        class_sql_pass += 1
                    else:
                        class_sql_fail += 1
                table.add_row(['数据库', class_sql_max, class_sql_min, class_sql_mean, class_sql_median, class_sql_pass,
                               class_sql_fail, class_sql_nums])
            print('\033[1;32m', end='')
            print('课程信息统计结果如下：')
            print('\033[1;31m', end='')
            print(table, end='')
            print('\033[0m')
    elif choice.lower() == 'm':
        print('=' * 30)
        print('|', end='')
        print('学生信息管理系统'.center(20), end='')
        print('|')
        print('|', end='')
        print('版本 V1.0'.center(26), end='')
        print('|')
        print('-' * 30)
        print('|', end='    ')
        print('   用户操作说明'.ljust(18), end='')
        print('|')
        print('-' * 30)
        print('|', end='   ')
        print("1. 添加学生信息".ljust(19), end='')
        print('|')
        print('|', end='   ')
        print("2. 删除学生信息".ljust(19), end='')
        print('|')
        print('|', end='   ')
        print("3. 修改学生信息".ljust(19), end='')
        print('|')
        print('|', end='   ')
        print("4. 查询学生信息".ljust(19), end='')
        print('|')
        print('|', end='   ')
        print("5. 打印所有学生信息".ljust(15), end='')
        print('|')
        print('|', end='   ')
        print("6. 课程信息统计".ljust(19), end='')
        print('|')
        print('|', end='   ')
        print("7. 打印系统菜单".ljust(19), end='')
        print('|')
        print('|', end='   ')
        print("8. 退出系统".ljust(21), end='')
        print('|')
        print('=' * 30)
    elif choice.lower() == 'q':
        print('感谢使用，欢迎下次再来！')
        break
    else:
        print('您的选择有误，请重新选择！')
    print('\033[0m', end='')
